package com.thread;

import java.util.Random;

/**
 * ConsumptionDemo--bdqnPractice
 * 线程中生产者与消费者的例子
 *
 * @author: Jovi
 * @createTime: 2017-10-31 17:32
 **/

class SharedData {

    //产品
    private char c;

    //信号量，初始未生产
    private int isProduced = 0;

    /**
     * 生产产品
     *
     * @param c
     */
    public synchronized void putShareChar(char c) {

        System.out.println("我是【生产者】我获得了SharedData对象锁");
        //还有剩余
        if (isProduced == 1) {
            try {
                System.out.println("消费者还未消费，因此停止生产（接下来生产者等待，并释放SharedData对象锁）");
                wait();
                System.out.println("生产者被唤醒，并进行生产");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.c = c;

        //标记已生产
        isProduced = 1;

        notify();//通知消费者已经生产，可以消费
        System.out.println("生产者唤醒【消费者】");

        System.out.println("我是生产者生产了产品" + c + "通知消费者消费，生产者释放SharedData对象锁");
    }

    /**
     * 消费产品
     *
     * @return
     */
    public synchronized char getShareChar() {

        System.out.println("我是【消费者】我获得了SharedData对象锁");

        /* 如果产品还未生产，则消费者等待 */
        if (isProduced == 0) {
            System.out.println("生产者还未生产，因此消费者停止消费(接下来消费者等待，并释放SharedData对象锁)");
            try {
                wait();
                System.out.println("消费者被唤醒，并进行消费");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //标记已经消费
        isProduced = 0;

        notify();//通知需要生产
        System.out.println("消费者唤醒【生产者】");

        System.out.println("消费者已经消费了产品" + c + "通知生产者生产，消费者释放SharedData对象锁");

        return c;
    }
}

/**
 * 生产者线程
 */
class Producer extends Thread {

    private SharedData s;

    Producer(SharedData s) {
        this.s = s;
    }

    private Random random = new Random();

    @Override
    public void run() {
        for (char ch = 'A'; ch <= 'D'; ch++) {
            try {
                Thread.sleep(random.nextInt(3000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            s.putShareChar(ch);
        }
    }
}

/**
 * 消费者
 */
class Consumer extends Thread {

    private SharedData s;

    Consumer(SharedData s) {
        this.s = s;
    }

    private Random random = new Random();

    @Override
    public void run() {
        char ch;

        do {
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            ch = s.getShareChar();
        } while (ch != 'D');
    }
}


class ConsumptionDemo {


    public static void main(String[] args) {

        SharedData s = new SharedData();

        Consumer consumer = new Consumer(s);
        consumer.setName("消费者");
        consumer.start();

        Producer producer = new Producer(s);
        producer.setName("生产者");
        producer.start();
    }


}




